import 'package:boss/color_constant.dart';
import 'package:boss/textStyle/text_style.dart';
import 'package:boss/ui/widget/calendar/util/date_util.dart';
import 'package:boss/ui/widget/center_title_app_bar.dart';
import 'package:boss/ui/widget/image/base_image.dart';
import 'package:boss/ui/widget/label_button.dart';
import 'package:hi_common/hi_common.dart';
import 'package:flutter/material.dart';
import 'package:flustars/flustars.dart' as flustars;

enum CalendarType {
  ymd,
  ymdhm,
  hm,
}

final _calendarTitle = {
  CalendarType.ymd: ['年', '月', '日'],
  CalendarType.ymdhm: ['年', '月', '日', '时', '分'],
  CalendarType.hm: ['时', '分'],
};

class CalendarBar extends StatelessWidget {
  final DateTime startDateTime;
  final DateTime endDateTime;
  final ValueChanged<List<DateTime>> onDateTimeChanged;
  final CalendarType type;
  final bool isSingle;
  final bool isShowIcon;
  final bool enabled;

  const CalendarBar({
    Key key,
    this.startDateTime,
    this.endDateTime,
    this.onDateTimeChanged,
    this.type = CalendarType.ymd,
    this.isSingle = false,
    this.isShowIcon = true,
    this.enabled = true,
  }) : super(key: key);

  Widget get startTimeText => startDateTime == null ? Text('请选择', style: TextStyleConstant().normal_4_26) : Text('${_formDate(startDateTime)}');

  Widget get endTimeText => endDateTime == null ? Text('请选择', style: TextStyleConstant().normal_4_26) : Text('${_formDate(endDateTime)}');

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () => pickerPage(context),
      child: Container(
        height: 60.w,
        decoration: BoxDecoration(
          border: Border.all(color: ColorConstant.e5e5, width: 1.px * 2),
          borderRadius: BorderRadius.circular(30.w),
        ),
        padding: EdgeInsets.symmetric(horizontal: 15.w),
        child: Row(
          children: <Widget>[
            if (isShowIcon) SizedBox(width: 30.w),
            Expanded(
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: <Widget>[
                  Expanded(
                    child: Container(
                      alignment: Alignment.center,
                      child: startTimeText,
                    ),
                  ),
                  if (!isSingle)
                    Text(
                      '~',
                      style: TextStyleConstant().normal_4_26,
                    ),
                  if (!isSingle)
                    Expanded(
                      child: Container(
                        alignment: Alignment.center,
                        child: endTimeText,
                      ),
                    ),
                ],
              ),
            ),
            if (isShowIcon)
              BaseImage(
                'assets/image/calendar_icon.png',
                width: 30.w,
                height: 30.w,
              ),
          ],
        ),
      ),
    );
  }

  String _formDate(DateTime dateTime) {
    switch (type) {
      case CalendarType.ymd:
        return flustars.DateUtil.formatDate(dateTime, format: flustars.DateFormats.y_mo_d);
      case CalendarType.ymdhm:
        return flustars.DateUtil.formatDate(dateTime, format: flustars.DateFormats.y_mo_d_h_m);
      case CalendarType.hm:
        return flustars.DateUtil.formatDate(dateTime, format: 'HH:mm');
    }

    return '';
  }

  void pickerPage(BuildContext context) async {
    final res = await openCalendarPicker(
      context,
      startDateTime: startDateTime,
      endDateTime: endDateTime,
      type: type,
      isSingle: isSingle,
    );
    if (res != null && onDateTimeChanged != null) {
      onDateTimeChanged(res);
    }
  }
}

Future<List<DateTime>> openCalendarPicker(
  BuildContext context, {
  DateTime startDateTime,
  DateTime endDateTime,
  CalendarType type,
  bool isSingle = false,
}) {
  return Navigator.push<List<DateTime>>(context, MaterialPageRoute(builder: (context) {
    return CalendarPickerPage(
      dateTimeTime: startDateTime,
      endDateTime: endDateTime,
      type: type,
      isSingle: isSingle,
    );
  }));
}

class CalendarPickerPage extends StatefulWidget {
  final DateTime dateTimeTime;
  final DateTime endDateTime;
  final CalendarType type;
  final bool isSingle;

  const CalendarPickerPage({
    this.dateTimeTime,
    this.endDateTime,
    this.type,
    this.isSingle,
    Key key,
  }) : super(key: key);

  @override
  _CalendarPickerPageState createState() => _CalendarPickerPageState();
}

class _CalendarPickerPageState extends State<CalendarPickerPage> {
  DateTime startDate;

  DateTime endDate;

  @override
  void initState() {
    super.initState();

    final now = DateTime.now();

    startDate = widget.dateTimeTime ?? DateUtils.startOfTheDay(now);
    endDate = widget.endDateTime ?? DateUtils.endOfTheDay(now);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: CenterTitleAppBar(
        title: '请选择',
        actions: [
          LabelButton(
            title: '确定',
            padding: EdgeInsets.only(left: 4, top: 2, bottom: 2),
            onTap: confirm,
          ),
        ],
      ),
      body: Column(
        children: [
          Padding(
            padding: EdgeInsets.symmetric(vertical: 10.w),
            child: Row(
              children: _calendarTitle[widget.type]
                  .map((item) => Expanded(
                        child: Center(child: Text(item, style: TextStyleConstant().normal_1_28)),
                      ))
                  .toList(),
            ),
          ),
          _PickerContainer(
            title: '起始时间',
            dateTime: startDate,
            onDateTimeChanged: onStartDateTimeChanged,
            type: widget.type,
          ),
          if (!widget.isSingle)
            _PickerContainer(
              title: '结束时间',
              dateTime: endDate,
              onDateTimeChanged: onEndDateTimeChanged,
              type: widget.type,
            ),
        ],
      ),
    );
  }

  void onStartDateTimeChanged(DateTime dateTime) {
    startDate = dateTime;
  }

  void onEndDateTimeChanged(DateTime dateTime) {
    endDate = dateTime;
  }

  void confirm() {
    Navigator.pop(context, [startDate, endDate]);
  }
}

class _PickerContainer extends StatefulWidget {
  final DateTime dateTime;
  final String title;
  final ValueChanged<DateTime> onDateTimeChanged;
  final CalendarType type;

  const _PickerContainer({
    @required this.dateTime,
    @required this.onDateTimeChanged,
    @required this.title,
    @required this.type,
    Key key,
  }) : super(key: key);

  @override
  __PickerContainerState createState() => __PickerContainerState();
}

class __PickerContainerState extends State<_PickerContainer> {
  FixedExtentScrollController yearScrollCon;
  FixedExtentScrollController monthScrollCon;
  FixedExtentScrollController dayScrollCon;
  FixedExtentScrollController hourScrollCon;
  FixedExtentScrollController minuteScrollCon;

  List<int> yearList;
  List<int> monthList;
  List<int> startDayList;
  List<int> endDayList;
  List<int> hourList;
  List<int> minuteList;

  final minDate = DateTime(1900);

  DateTime dateTime;

  @override
  void initState() {
    super.initState();
    final now = DateTime.now();

    dateTime = widget.dateTime;

    yearList = List.generate(now.year - minDate.year + 1, (index) => minDate.year + index);
    monthList = List.generate(12, (index) => index + 1);
    startDayList = getDaysByMonth(dateTime);
    hourList = List.generate(24, (index) => index);
    minuteList = List.generate(60, (index) => index);

    yearScrollCon = FixedExtentScrollController(initialItem: dateTime2Index(dateTime, 0));
    monthScrollCon = FixedExtentScrollController(initialItem: dateTime2Index(dateTime, 1));
    dayScrollCon = FixedExtentScrollController(initialItem: dateTime2Index(dateTime, 2));
    hourScrollCon = FixedExtentScrollController(initialItem: dateTime2Index(dateTime, 3));
    minuteScrollCon = FixedExtentScrollController(initialItem: dateTime2Index(dateTime, 4));
  }

  @override
  void dispose() {
    yearScrollCon.dispose();
    monthScrollCon.dispose();
    dayScrollCon.dispose();
    hourScrollCon.dispose();
    minuteScrollCon.dispose();

    super.dispose();
  }

  int dateTime2Index(DateTime dateTime, int type) {
    if (type == 0) {
      return yearList.indexOf(dateTime.year);
    } else if (type == 1) {
      return monthList.indexOf(dateTime.month);
    } else if (type == 2) {
      return getDaysByMonth(dateTime).indexOf(dateTime.day);
    } else if (type == 3) {
      return hourList.indexOf(dateTime.hour);
    } else {
      return minuteList.indexOf(dateTime.minute);
    }
  }

  List<int> getDaysByMonth(DateTime dateTime) {
    final days = DateUtils.getDaysInMonth(dateTime);

    return List.generate(days, (index) => index + 1);
  }

  void onYearChanged(int index) {
    dateTime = DateTime(minDate.year + index, dateTime.month, dateTime.day, dateTime.hour, dateTime.minute);

    widget.onDateTimeChanged(dateTime);
  }

  void onMonthChanged(int index) {
    final days = getDaysByMonth(DateTime(dateTime.year, index + 1));
    if (days.length != startDayList.length) {
      dayScrollCon.dispose();
      dayScrollCon = null;
      dayScrollCon = FixedExtentScrollController(initialItem: dateTime2Index(dateTime, 2));

      setState(() {
        startDayList = List.from(days);
      });
    }

    dateTime = DateTime(dateTime.year, index + 1, dateTime.day, dateTime.hour, dateTime.minute);
    widget.onDateTimeChanged(dateTime);
  }

  void onDayChanged(int index) {
    dateTime = DateTime(dateTime.year, dateTime.month, index + 1, dateTime.hour, dateTime.minute);
    widget.onDateTimeChanged(dateTime);
  }

  void onHourChanged(int index) {
    dateTime = DateTime(dateTime.year, dateTime.month, dateTime.day, index, dateTime.minute);
    widget.onDateTimeChanged(dateTime);
  }

  void onMinuteChanged(int index) {
    dateTime = DateTime(dateTime.year, dateTime.month, dateTime.day, dateTime.hour, index);
    widget.onDateTimeChanged(dateTime);
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Container(
          height: 90.w,
          alignment: Alignment.center,
          color: ColorConstant.ffcc,
          child: Text(widget.title, style: TextStyleConstant().normal_1_30.copyWith(fontWeight: FontWeight.bold)),
        ),
        Container(
          height: 60.w * 8,
          child: Row(
            children: [
              buildListWheel(yearList, yearScrollCon, onSelectedItemChanged: onYearChanged),
              buildListWheel(monthList, monthScrollCon, onSelectedItemChanged: onMonthChanged),
              buildListWheel(startDayList, dayScrollCon, onSelectedItemChanged: onDayChanged),
              if ([CalendarType.ymdhm, CalendarType.hm].contains(widget.type)) buildListWheel(hourList, hourScrollCon, onSelectedItemChanged: onHourChanged),
              if ([CalendarType.ymdhm, CalendarType.hm].contains(widget.type))
                buildListWheel(minuteList, minuteScrollCon, onSelectedItemChanged: onMinuteChanged),
            ],
          ),
        ),
      ],
    );
  }

  Widget buildListWheel(List<int> data, ScrollController scrollController, {ValueChanged<int> onSelectedItemChanged}) {
    return Expanded(
      child: Stack(
        alignment: Alignment.centerLeft,
        children: [
          ListWheelScrollView.useDelegate(
            key: ValueKey(data.length),
            itemExtent: 60.w,
            controller: scrollController,
            physics: const FixedExtentScrollPhysics(),
            childDelegate: ListWheelChildBuilderDelegate(
              builder: (context, index) {
                return Container(
                  alignment: Alignment.center,
                  child: Text('${data[index]}', style: TextStyleConstant().normal_1_28),
                );
              },
              childCount: data.length,
            ),
            onSelectedItemChanged: onSelectedItemChanged,
          ),
          Positioned(
            child: IgnorePointer(
              child: Container(
                height: 60.w,
                decoration: BoxDecoration(
                  border: Border(
                    top: BorderSide(color: ColorConstant.ffcc, width: 1.px),
                    bottom: BorderSide(color: ColorConstant.ffcc, width: 1.px),
                  ),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}
